import _mathlink
import Mathematica
import tempfile
import string
import os


HEADER_FILENAME="header.ps"
FOOTER_FILENAME="footer.ps"

PYMLTKFUNC=0
PYMLTKINT=1
PYMLTKREAL=2
PYMLTKSTR=3
PYMLTKSYM=4
PYMLTKERROR=5

ILLEGALPKT=      0
INPUTPKT=        1
TEXTPKT=         2
RETURNPKT=       3
RETURNTEXTPKT=   4
MESSAGEPKT=      5
MENUPKT=         6
CALLPKT=         7
INPUTNAMEPKT=    8
OUTPUTNAMEPKT=   9
SYNTAXPKT=      10
DISPLAYPKT=     11
DISPLAYENDPKT=  12
EVALUATEPKT=    13
ENTERTEXTPKT=   14
ENTEREXPRPKT=   15
RETURNEXPRPKT=  16
SUSPENDPKT=     17
RESUMEPKT=      18
BEGINDLGPKT=    19
ENDDLGPKT=      20
INPUTSTRPKT=    21
FIRSTUSERPKT=  128
LASTUSERPKT=   255


class MathematicaResponse:
    def __init__(self):
	self.displaypkt = ""
    
    
    def process(self):
	_mathlink.Flush()
	while(1):
	    pkt = _mathlink.NextPacket()
	    if pkt == INPUTNAMEPKT:
		MathematicaInputNamePacket().handle()
	    elif pkt == DISPLAYPKT:
		self.displaypkt = self.displaypkt + MathematicaDisplayPacket().handle()
	    elif pkt == DISPLAYENDPKT:
		MathematicaDisplayEndPacket().handle()
	    elif pkt == MESSAGEPKT:
		MathematicaMessagePacket().handle()
	    elif pkt == TEXTPKT:
		MathematicaTextPacket().handle()
	    elif pkt == RETURNTEXTPKT:
		MathematicaReturnTextPacket().handle()
	    elif pkt == RETURNPKT:
		packet = MathematicaReturnPacket()
		self.DisplayPacket()
		return packet.handle(0, None)
	    else:
		packet = MathematicaUnhandledPacket(pkt)
	    _mathlink.NewPacket()

    def DisplayPacket(self):
	if self.displaypkt != "":
	    filename = tempfile.mktemp() + ".eps"
	    f= open(filename, "w")
	    f.write(open(HEADER_FILENAME).read())
            f.write(self.displaypkt)
            f.write(open(FOOTER_FILENAME).read())
	    f.close()
            print "Stored EPS file as", filename

class MathematicaPacket:
    def __init__(self):
	pass

class MathematicaUnhandledPacket:
    def __init__(self):
	MathematicaPacket.__init__(self)

    def handle(self, pkt):
	print "Cannot handle pkt==", pkt

class MathematicaReturnPacket(MathematicaPacket):
    def __init__(self):
	MathematicaPacket.__init__(self)

    def handle(self, level,expr):
	next = _mathlink.GetNext()
	if next == PYMLTKFUNC:
	    function, n = _mathlink.GetFunction()
	    subexpr = []
	    for i in range(n):
		packet = MathematicaReturnPacket()
		packet.handle(level+1, subexpr)
	    if level == 0:
		expr = Mathematica.MathematicaExpression(Mathematica.MathematicaFunction(function,subexpr))
	    else:
		expr.append(Mathematica.MathematicaFunction(function,subexpr))

	elif next == PYMLTKSYM:
	    symbol = _mathlink.GetSymbol()
	    if level == 0:
		expr = Mathematica.MathematicaExpression(Mathematica.MathematicaSymbol(symbol))
	    else:
		expr.append(Mathematica.MathematicaSymbol(symbol))
	    return expr
	elif next == PYMLTKSTR:
	    text = _mathlink.GetString()
	    if level == 0:
		expr = Mathmatica.MathematicaExpression(Mathematica.MathematicaString(text))
	    else:
		expr.append(Mathematica.MathematicaString(text))
	    return expr
	elif next == PYMLTKINT:
	    integer = _mathlink.GetInteger()
	    if level == 0:
		expr = Mathematica.MathematicaExpression(Mathematica.MathematicaInteger(integer))
	    else:
		expr.append(Mathematica.MathematicaInteger(integer))
	    return expr
	elif next == PYMLTKREAL:
	    real = _mathlink.GetReal()
	    if level == 0:
		expr = MathematicaExpression(MathematicaReal(real))
	    else:
		expr.append(Mathematica.MathematicaReal(real))
	    return expr
	elif next == PYMLTKERROR:
	    print "error: no match"
	    expr.append(None)
	    return expr
	else:
	    print "failure to match"
	    expr.append(None)
	    return expr
	return expr

class MathematicaMessagePacket(MathematicaPacket):
    def __init__(self):
	MathematicaPacket.__init__(self)

    def handle(self):
	symbol = _mathlink.GetSymbol()
	text = _mathlink.GetString()
	print "Message: symbol=", symbol
	print "Message: text=", text

class MathematicaTextPacket(MathematicaPacket):
    def __init__(self):
	MathematicaPacket.__init__(self)

    def handle(self):
	text = _mathlink.GetString()
	print "Text: text=", text

class MathematicaReturnTextPacket(MathematicaPacket):
    def __init__(self):
	MathematicaPacket.__init__(self)

    def handle(self):
	text = _mathlink.GetString()
	print "ReturnText: text=", text

class MathematicaInputNamePacket(MathematicaPacket):
    def __init__(self):
	MathematicaPacket.__init__(self)

    def handle(self):
	text = _mathlink.GetString()
	print "InputName: text=", text


class MathematicaDisplayPacket(MathematicaPacket):
    def __init__(self):
	MathematicaPacket.__init__(self)

    def handle(self):
	text = _mathlink.GetByteString()
	return text


class MathematicaDisplayEndPacket(MathematicaPacket):
    def __init__(self):
	MathematicaPacket.__init__(self)

    def handle(self):
	text = _mathlink.GetString()
## 	print "DisplayEnd: text=", text
